/*
 * @Date: 2023-02-15 14:36:19
 * @LastEditTime: 2023-09-07 16:35:36

 * 介绍:
 */
import axios, {
  AxiosInstance,
  AxiosRequestConfig,
  CreateAxiosDefaults,
} from "axios";

export interface IsSuccess<D = any> {
  (res: D): IsSuccessRet;
}
export interface IsSuccessRet {
  success: boolean;
  message: string;
}
export interface ShowRequestAlert {
  (message: string): any;
}
export interface MyCongfig {
  isSuccess: IsSuccess;
  showLoading: ShowRequestAlert;
  showFail: ShowRequestAlert;
  showSuccess: ShowRequestAlert;
  hidLoading: () => any;
  filterReq(p: AnyObject): AnyObject;
}

export default class Request {
  /**axios实例 */
  public axios: AxiosInstance;
  constructor(config: CreateAxiosDefaults = {}, private myConfig: MyCongfig) {
    this.axios = axios.create(config);
    /**
     * * 请求拦截器
     */
    this.axios.interceptors.request.use(<any>((
      config: RequestConfig
    ): AxiosRequestConfig => {
      const { showLoading, loadingMsg } = this.helper(config?.mode);
      if (config.mode?.filterReq) {
        config.data = this.myConfig.filterReq(config.data);
        config.params = this.myConfig.filterReq(config.params);
        config.headers = this.myConfig.filterReq({ ...config.headers });
      }
      if (showLoading) {
        this.myConfig.showLoading(loadingMsg);
      }
      return config;
    }));
    /**
     * * 响应拦截器
     */
    this.axios.interceptors.response.use(
      (response) => {
        const data = response.data;
        return Promise.resolve(data);
      },
      (error) => {
        //对错误进行统一处理
        return Promise.resolve(error);
      }
    );
  }
  public async get<T>(
    url: string,
    params: object | void,
    config?: RequestConfig
  ): Promise<T> {
    const res: any = await this.axios({
      ...config,
      url,
      params,
      method: "GET",
    });
    if (this.myConfig.isSuccess(res)) {
      return this.successAfter(res, config?.mode);
    }
    return this.failAfter(res, config?.mode);
  }
  public async post<T>(
    url: string,
    data: object | void,
    config?: RequestConfig
  ): Promise<T> {
    const res: any = await this.axios({
      ...config,
      url,
      data,
      method: "POST",
    });

    if (this.myConfig.isSuccess(res)) {
      return this.successAfter(res, config?.mode);
    }
    return this.failAfter(res, config?.mode);
  }
  public async put<T>(
    url: string,
    data: object | void,
    config?: RequestConfig
  ): Promise<T> {
    const res: any = await this.axios({
      ...config,
      url,
      data,
      method: "PUT",
    });
    if (this.myConfig.isSuccess(res)) {
      return this.successAfter(res, config?.mode);
    }
    return this.failAfter(res, config?.mode);
  }
  public async delete<T>(
    url: string,
    data: object | void,
    config?: RequestConfig
  ): Promise<T> {
    const res: any = await this.axios({
      ...config,
      url,
      data,
      method: "DELETE",
    });

    if (this.myConfig.isSuccess(res)) {
      return this.successAfter(res, config?.mode);
    }
    return this.failAfter(res, config?.mode);
  }
  private successAfter(res: any, mode: Mode | undefined): typeof res {
    const { showSuccessMsg, successMsg, showLoading } = this.helper(mode);
    if (showSuccessMsg) this.myConfig.showSuccess(successMsg);
    if (showLoading) this.myConfig.hidLoading();
    return res;
  }
  private failAfter(res: any, mode: Mode | undefined): typeof res {
    const { showFailMsg, failMsg, showLoading } = this.helper(mode);
    if (showFailMsg) this.myConfig.showFail(failMsg);
    if (showLoading) this.myConfig.hidLoading();
    return res;
  }
  private helper(mode: Mode | undefined) {
    const loadingMessage = mode?.loadingMessage;
    const showLoading =
      loadingMessage === true || typeof loadingMessage === "string";
    const loadingMsg =
      typeof loadingMessage === "string" ? loadingMessage : "Loading...";

    const successMessage = mode?.successMessage;
    const showSuccessMsg =
      successMessage === true || typeof successMessage === "string";
    const successMsg =
      typeof successMessage === "string" ? successMessage : "Success";

    const failMessage = mode?.failMessage;
    const showFailMsg = failMessage === true || typeof failMessage === "string";
    const failMsg = typeof failMessage === "string" ? failMessage : "Fail";

    const errorMessage = mode?.errorMessage;
    const showErrorMsg =
      errorMessage === true || typeof errorMessage === "string";
    const errorMsg =
      typeof errorMessage === "string" ? errorMessage : "Network error";

    return {
      showLoading,
      loadingMsg,
      showFailMsg,
      failMsg,
      showSuccessMsg,
      successMsg,
      showErrorMsg,
      errorMsg,
    };
  }
}
/**请求配置 */
export interface RequestConfig extends AxiosRequestConfig {
  mode?: Mode;
}

export interface Mode {
  failMessage?: string | boolean;
  successMessage?: string | boolean;
  loadingMessage?: string | boolean;
  filterReq?: boolean;
  errorMessage?: string | boolean;
}
